package com.hyacinth.utils.file;

import com.hyacinth.utils.ArrayUtils;
import com.hyacinth.utils.SerialUtils;
import com.hyacinth.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class FileUtils extends org.apache.commons.io.FileUtils{

    private static final Logger log = LoggerFactory.getLogger(FileUtils.class);

    /**
     * 获取标准的绝对路径
     *
     * @param file 文件
     * @return 绝对路径
     */
    public static String getAbsolutePath(File file) {
        if (file == null) {
            return null;
        }
        try {
            return file.getCanonicalPath();
        } catch (IOException e) {
            return file.getAbsolutePath();
        }
    }

    /**
     * 获取文件后缀
     * @param path 文件全路径（包含文件名）
     * @return 后缀
     */
	public static String GetFileExt(String path) {
        if (StringUtils.isBlank(path)) {
            throw new RuntimeException("文件路径不能为空");
        }
		String ext = null;
		int i = path.lastIndexOf('.');
		if (i > 0 && i < path.length() - 1) {
			ext = path.substring(i + 1).toLowerCase();
		}
		return ext;
	}

    /**
     * 根据文件路径创建文件
     * @param path  源文件全路径（包含文件名）
     * @param fileName 新文件名  可选
     */
    public static File createFile(String path, String fileName) throws IOException {
        if (StringUtils.isBlank(path)) {
            throw new RuntimeException("文件路径不能为空");
        }
        if (StringUtils.isBlank(fileName)) {
            fileName = SerialUtils.genFileName();
        }
        File dir = new File(path);
        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                log.error("创建文件目录失败，path|"+path);
                throw new RuntimeException("创建文件目录失败");
            }
        }
        String filePath = path + File.separatorChar + fileName;
        File file = new File(filePath);
        if (!file.exists()) {
            if (!file.createNewFile()) {
                log.error("文件创建失败，file|"+filePath);
                throw new RuntimeException("文件创建失败");
            }
        }
        log.info("文件创建成功，file|"+filePath);
        return file;
    }

    /**
     * 根据源文件路径创建新文件
     * @param sourcePath  源文件全路径（包含文件名）
     * @param newFileName 新文件名  可选
     * @param filePostfix 新文件后缀
     */
	public static File createNewFileBySource(String sourcePath, String newFileName, String filePostfix) throws IOException {
		if (StringUtils.isBlank(sourcePath)) {
		    throw new RuntimeException("源文件路径不能为空");
        }
		if (StringUtils.isBlank(filePostfix)) {
		    throw new RuntimeException("文件后缀不能为空");
        }
        if (!new File(sourcePath).exists()) {
            throw new RuntimeException("源文件不存在");
        }
	    int i = sourcePath.lastIndexOf(File.separatorChar);
	    int j = sourcePath.lastIndexOf('.');
	    if (i == -1 || j == -1) {
            throw new RuntimeException("源文件路径不正确");
        }
		String dirPath = "";
		if (i > 0 && i < sourcePath.length() - 1) {
			dirPath = sourcePath.substring(0, i).toLowerCase();
		}
        if (StringUtils.isBlank(newFileName)) {
            newFileName = sourcePath.substring(i+1, sourcePath.lastIndexOf('.'));
        }
        newFileName = dirPath + File.separatorChar + newFileName + "." + filePostfix;
        File file = new File(newFileName);
        if (!file.exists()) {
            if (!file.createNewFile()) {
                log.error("文件创建失败，file|"+newFileName);
                throw new RuntimeException("文件创建失败");
            }
        }
        log.info("文件创建成功，file|"+newFileName);
        return file;
	}


    public static boolean isFile(File file) {
        return (file != null) && file.isFile();
    }

    /**
     * 递归遍历目录以及子目录中的所有文件<br>
     * 如果提供file为文件，直接返回过滤结果
     *
     * @param file 当前遍历文件或目录
     * @param fileFilter 文件过滤规则对象，选择要保留的文件，只对文件有效，不过滤目录
     * @return 文件列表
     */
    public static List<File> loopFiles(File file, FileFilter fileFilter) {
        List<File> fileList = new ArrayList<File>();
        if (null == file) {
            return fileList;
        } else if (!file.exists()) {
            return fileList;
        }

        if (file.isDirectory()) {
            final File[] subFiles = file.listFiles();
            if (ArrayUtils.isNotEmpty(subFiles)) {
                for (File tmp : subFiles) {
                    fileList.addAll(loopFiles(tmp, fileFilter));
                }
            }
        } else {
            if (null == fileFilter || fileFilter.accept(file)) {
                fileList.add(file);
            }
        }

        return fileList;
    }
}
